/************************************************************************
 * @file StandardMainWindow.cpp
 * @author Ian Chen
 * @version 1.0
 *
 * @section LICENSE
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details at
 * http://www.gnu.org/licenses/lgpl.html
 *
 ************************************************************************/
#include <QByteArray>
#include <QCoreApplication>
#include <QMessageBox>
#include <QSettings>

#include <plugin/util/Framework.h>

#include <pluginui/manager/ConfigPanelManager.h>
#include <pluginui/widget/ConfigDialog.h>

#include <plugin/util/PluginDescriptionManager.h>

#include <pluginui/activator/GuiPluginActivator.h>
#include <pluginui/extension/AbstractExtension.h>
#include <pluginui/extension/StandardMainWindowExtension.h>
#include <pluginui/widget/StandardMainWindow.h>

#include <pluginui/widget/SplashScreen.h>
#include <pluginui/widget/StandardAboutDialog.h>
#include <pluginui/widget/StandardPluginListDialog.h>

using namespace antu::widget;

namespace antu
{
namespace plugin
{
namespace ui
{
StandardMainWindow::StandardMainWindow(PluginContext* pContext,
                                       AbstractSecurityContextHandler* pHandler,
                                       const QPixmap& splash) :
    QMainWindow(nullptr),
    m_pContext(pContext)
{
    Q_ASSERT(this->m_pContext != nullptr);

    this->m_pConfigPanelManager = new ConfigPanelManager;
    this->m_pContext->addContextObject(ConfigPanelManager::Name, this->m_pConfigPanelManager);

    antu::plugin::Framework::Instance.setup(this->m_pContext, pHandler);

    Framework::Instance.loadTranslationFile(this->m_oTranslator, "pluginui");
    ////-------------------------Above this line is a
    //// one shot deal. Only need to do this once in an application.

    // Create an AbstractExtension for UI extension points.
    AbstractExtension* pExtension = new StandardMainWindowExtension(this);
    // Create PluginActivator, as this brings up a standalone window.
    this->m_pActivator = new GuiPluginActivator(pExtension);

    AbstractMenuManager* pManager = ((GuiPluginActivator*)this->m_pActivator)->extension()->menuManager();

    if (pManager != nullptr)
        pManager->menu("fileMenu", tr("&File"));

    // Bring up the splash window.
    SplashScreen* pSplash;

    if (splash.isNull())
        pSplash = new SplashScreen(this, QPixmap(":/resources/images/startup.png"));
    else
        pSplash = new SplashScreen(this, splash);
    pSplash->show();

    // Init PluginActivator, use splash window as load feedback
    this->m_pActivator->init(this, pSplash);
    this->m_pActivator->start(pSplash, true);

    //bool restoreResult = false;

    // load window position/size/state
//    QByteArray state = Framework::Instance.settingsManager()->value("window/state").toByteArray();
//    if (!state.isNull() && !state.isEmpty())
//        restoreResult = this->restoreState(state);

    //QByteArray geometry = Framework::Instance.settingsManager()->value("window/geometry").toByteArray();
    //if (!geometry.isNull() && !geometry.isEmpty())
    //    restoreResult = this->restoreGeometry(geometry);

    this->m_pActivator->finishStartup(pSplash);

    this->m_sSerialNumber = "0000 0000 0000 0000 0000";
    this->m_sProductName = this->m_sTitle = this->windowTitle();
    this->m_sVersion = "1.0.0.0";

    this->initInterface();

    pSplash->close();
    delete pSplash;
}

StandardMainWindow::~StandardMainWindow()
{
//    QByteArray geometry = this->saveGeometry();
//    QByteArray state = this->saveState();

//    Framework::Instance.settingsManager()->setValue("window/geometry", geometry);
//    Framework::Instance.settingsManager()->setValue("window/state", state);

    // stops all plugins
    this->m_pActivator->stop();
    delete this->m_pActivator;
}

void StandardMainWindow::setApplicationTitle(const QString &title)
{
    if (!title.isEmpty())
    {
        this->m_sTitle = title;
        this->setWindowTitle(title);
    }
}

void StandardMainWindow::setVersion(const QString &version)
{
    if (!version.isEmpty())
    {
        this->m_sVersion = version;
    }
}

void StandardMainWindow::setProductName(const QString &name)
{
    if (!name.isEmpty())
        this->m_sProductName = name;
}

void StandardMainWindow::setSerialNumber(const QString &serial)
{
    if (!serial.isEmpty())
        this->m_sSerialNumber = serial;
}

void StandardMainWindow::setAboutImage(const QPixmap &image)
{
    this->m_oAboutImage = image;
}

void StandardMainWindow::initInterface()
{
    if (((GuiPluginActivator*)this->m_pActivator)->extension()->menuManager() != nullptr)
    {
        AbstractMenuManager* pManager = ((GuiPluginActivator*)this->m_pActivator)->extension()->menuManager();

        QMenu* pFileMenu = pManager->menu("fileMenu", tr("&File"));
        if (!pFileMenu->isEmpty())
        {
            pFileMenu->addSeparator();
        }
        QAction* pAction = pFileMenu->addAction(tr("E&xit"));
        this->connect(pAction, SIGNAL(triggered()), qApp, SLOT(quit()));

        if (Framework::Instance.descriptionManager()->descriptionCount() > 0)
        {
            QMenu* pToolMenu = pManager->menu("toolMenu", tr("&Tools"));
            if (!pToolMenu->isEmpty())
                pToolMenu->addSeparator();
            QAction* pListAction = pToolMenu->addAction(tr("Plugin list..."));
            this->connect(pListAction, SIGNAL(triggered()), this, SLOT(pluginListClicked()));
        }

        QObject* pContextObject = (*Framework::Instance.context())[ConfigPanelManager::Name];
        if (pContextObject != nullptr)
        {
            ConfigPanelManager* pConfigPanelManager = qobject_cast<ConfigPanelManager*>(pContextObject);
            if (pConfigPanelManager != nullptr && !pConfigPanelManager->isEmpty())
            {
                QMenu* pToolMenu = pManager->menu("toolMenu", tr("&Tools"));
                QAction* pConfigAction = pToolMenu->addAction(tr("Pereferences..."));
                this->connect(pConfigAction, SIGNAL(triggered()), this, SLOT(configClicked()));
            }
        }

        QMenu* pHelpMenu = pManager->menu("helpMenu", tr("&Help"));
        if (!pHelpMenu->isEmpty())
            pHelpMenu->addSeparator();
        QAction* pAboutAction = pHelpMenu->addAction(tr("&About..."));
        this->connect(pAboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
    }
}

void StandardMainWindow::aboutClicked()
{
    StandardAboutDialog* pDialog = new StandardAboutDialog(this->m_sTitle,
                                                           this->m_sProductName,
                                                           this->m_sVersion,
                                                           this->m_sSerialNumber,
                                                           this->m_oAboutImage,
                                                           this);
    pDialog->exec();
    delete pDialog;
}

void StandardMainWindow::pluginListClicked()
{
    StandardPluginListDialog* pDialog = new StandardPluginListDialog(this);
    pDialog->exec();
    delete pDialog;
}

void StandardMainWindow::configClicked()
{
    QObject* pContextObject = (*Framework::Instance.context())[ConfigPanelManager::Name];
    if (pContextObject != nullptr)
    {
        ConfigPanelManager* pConfigPanelManager = qobject_cast<ConfigPanelManager*>(pContextObject);
        if (pConfigPanelManager != nullptr && !pConfigPanelManager->isEmpty())
        {
            ConfigDialog* pDialog = new ConfigDialog(pConfigPanelManager, this);
            pDialog->exec();
            delete pDialog;
        }
    }
}

void StandardMainWindow::closeEvent(QCloseEvent *pEvent)
{
    CloseSignal signal;
    Framework::Instance.stop(&signal);

    if (signal.canClose())
        QWidget::closeEvent(pEvent);
}

}
}
}

